import requests
from bs4 import BeautifulSoup
import time
import os
import pandas
import re
import base64
from pyDes import des, CBC, PAD_PKCS5
from styleframe import StyleFrame
class schoolSpider:
    def __init__(self):
        #爬虫所需要的头部及url
        self.session = requests.Session()
        self.headers = {
            'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.87 Safari/537.36 SE 2.X MetaSr 1.0'}
        self.headerss = {
            'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.87 Safari/537.36 SE 2.X MetaSr 1.0',
            'Referer': 'http://jw.gzkmu.edu.cn/(2e1uwl3keswsd055iollwaip)/xscjcx.aspx?xh=19153110232&xm=%CE%E2%BD%A3%BA%C0&gnmkdm=N121605'}
        self.urla = 'http://r.gzkmu.edu.cn/zfca/login?yhlx=student&login=0122579031373493708&url=xs_main.aspx'
        self.urlb = 'http://r.gzkmu.edu.cn/zfca?yhlx=student&login=0122579031373493708&url=xscjcx.aspx'

        #程序的开始控制端口
        while True:
            print("=输入账号密码获取成绩")
            self.S = input("=账号:")
            self.M = input("=密码:")
            print("*功能读取中....*")
            time.sleep(1)
            try:
                if len(self.S) == 11:
                    self.user()
                    continue
                else:
                    print("=账号密码错误请重新输入")
            except Exception as e:
                print(f"读取成绩错误:{e}:请重试")

    # 账号密码加密程序
    def des_cbc_encrypt_text(self,decrypt_text: str, key: str) -> str:
        """
        加密DES_CBC明文
        :param decrypt_text: 明文
        :param key: 密钥
        :param iv: 密钥偏移量
        :return: 加密后的数据
        """
        des_obj = des(key[:8].encode('utf-8'), pad=None, padmode=PAD_PKCS5)
        encrypt_text = des_obj.encrypt(decrypt_text)
        encrypt_text = str(base64.encodebytes(encrypt_text), encoding='utf-8').replace("\n", "")
        return encrypt_text

    def user(self):
        key_str = "12345678"
        zh = self.des_cbc_encrypt_text(self.S, key_str)
        mm = self.des_cbc_encrypt_text(self.M, key_str)
        # 所需要返回的POST值
        self.data = {'username': zh,
                'password': mm,
                '_eventId': 'submit',
                'lt': schoolSpider.code(self)
                }
        if self.data['lt'] == '错误':
            print('网页IT值获取失败')
            return " "
        self.always()

#账号调用
    def always(self):
        res = self.session.post(url=self.urla, data=self.data, headers=self.headers)
        time.sleep(1)
        b = re.search(r'<title>.*?</title>', res.text)
        if b.group(0) == '<title>错误提示页面</title>':
            time.sleep(1)
            print('*账号密码错误*')
            time.sleep(1)
            print('*返回主页面*')
            print()
            return '错误'
        time.sleep(1)
        ddd = res.status_code
        if not os.path.exists('成绩表.xlsx'):
            if ddd == 200:
                print("*系统进入成功，尝试进入成绩系统*")
                time.sleep(1)
                ress = self.session.post(url=self.urlb, headers=self.headers)
                self.urlc = ress.url
                print("*成绩系统进入成功，正在清洗数据*")
                time.sleep(1)
                self.CJ()
                res.close()
                ress.close()
                time.sleep(1)
                exit()
            else:
                print('*报错', '*无法访问页面*')
                print('*退出程序*')
                res.close()
                exit()
        else:
            print("*成绩表文件以存在，请删除再运行*")
            print("*软件制作者：19届云计算2班吴剑豪*")

    #返回数据所需要的值
    def code(self):
        page_text = self.session.get(self.urla, headers=self.headers)
        time.sleep(1)
        # print(page_text)
        soup = BeautifulSoup(page_text.text, "html.parser")
        It = soup.find_all('input')
        code_a = It[-3].attrs['value']
        # print(code_a)
        return str(code_a)

#数据清洗及保存
    def CJ(self):
        main = []
        self.cj = {'姓名': ['基本信息'],
              '学年': ['学年'],
              '学期': ['学期'],
              '课程名称': ['课程名称'],
              '课程性质': ['课程性质'],
              '学分': ['学分'],
              '绩点': ['绩点'],
              '平时成绩': ['平时成绩'],
              '期末成绩': ['期末成绩'],
              '实验成绩': ['实验成绩'],
              '成绩': ['成绩'],
              '开课学院': ['开课学院']
              }
        res = self.session.post(url=self.urlc, data=self.code1(), headers=self.headerss)
        self.html = res.text
        time.sleep(1)
        soup = BeautifulSoup(res.text, "html.parser")
        for tr in soup.find_all('tr'):
            for td in tr.find_all('td'):
                rt = str(td.get_text())
                main.append(rt)
        print("*数据清洗成功,正在加载表格*")
        print("tip:若需要定制内置账号请联系作者")

        time.sleep(1)
        for i in main[1:6]:
            self.cj['姓名'].append(i)
        main = main[25:]
        for i in range(int((len(main) - 20) / 19)):
            i = i * 19
            self.cj['学年'].append(main[i])
            self.cj['学期'].append(main[i + 1])
            self.cj['课程名称'].append(main[i + 3])
            self.cj['课程性质'].append(main[i + 4])
            self.cj['学分'].append(main[i + 6])
            self.cj['绩点'].append(main[i + 7])
            self.cj['平时成绩'].append(main[i + 8])
            self.cj['期末成绩'].append(main[i + 10])
            self.cj['实验成绩'].append(main[i + 11])
            self.cj['成绩'].append(main[i + 12])
            self.cj['开课学院'].append(main[i + 16])
            # print(cj)
            self.df = pandas.DataFrame.from_dict(self.cj, orient='index')
        print("*数据清洗成功请选择接来下的操作*")
        print("*软件制作者：19届云计算2班吴剑豪*")

        self.main()

    def main(self):
        time.sleep(1)
        print()
        while True:
            print("=输入1保存网页文件")
            print("=输入2保存表格文件")
            print("=输入3查看成绩表")
            print("=输入任意数字退出程序")
            a = eval(input("你的选择:"))
            try:
                if a == 1:
                    if not os.path.exists('成绩表.html'):
                        with open("成绩表.html", "w") as f:
                            f.write(self.html)
                            print()
                            print("*成绩表.html生成成功*")
                            print("*软件制作者：19届云计算2班吴剑豪*")
                            print()
                    else:
                        print()
                        print("*以存在网页文件*")
                        print("*软件制作者：19届云计算2班吴剑豪*")

                        print()
                elif a == 2:
                    if not os.path.exists('成绩表.xlsx'):
                        # self.df.to_excel('成绩表.xlsx',startrow=5)
                        excel_writer = StyleFrame.ExcelWriter('成绩表.xlsx')
                        sf = StyleFrame(self.df)
                        sf.to_excel(
                            excel_writer=excel_writer,
                            columns_and_rows_to_freeze='B2',
                            row_to_add_filters=0,
                        )
                        excel_writer.save()
                        print()
                        print("*成绩表.xlsx生成成功*")
                        print("*软件制作者：19届云计算2班吴剑豪*")
                        print()
                    else:
                        print()
                        print("*以存在网页文件*")
                        print("*软件制作者：19届云计算2班吴剑豪*")
                        print()
                elif a == 3:
                    print(self.df.values)
                else:
                    print("*软件制作者：19届云计算2班吴剑豪*")
                    exit()
                continue
            except Exception as e:
                print(f"功能调用错误错误:{e}:请重试")
                continue
#获取数据的相关代码
    def code1(self):
        b = self.session.get(self.urlc, headers=self.headerss)
        soup = BeautifulSoup(b.text, "html.parser")
        It = soup.find_all('input')
        code_a = It[2].attrs['value']
        data = {
            '__EVENTTARGET': '',
            '__EVENTARGUMENT': '',
            'ddlXN': '',
            'ddlXQ': '',
            'ddl_kcxz': '',
            'btn_zcj': '历年成绩'.encode('gb2312')
        }
        data['__VIEWSTATE'] = str(code_a)
        return data

if __name__ == '__main__':
    print("*************************")
    print("*************************")
    print("*************************")
    print("*************************")
    print("*************************")
    print("*************************")
    time.sleep(5)
    schoolSpider()
